package com.teamwings.modules.head.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.teamwings.common.constant.FormConstant;
import com.teamwings.common.exception.ResultException;
import com.teamwings.modules.code.entity.FormTableCode;
import com.teamwings.modules.code.mapper.FormTableCodeMapper;
import com.teamwings.modules.design.mapper.DesignMapper;
import com.teamwings.modules.design.service.IDesignService;
import com.teamwings.modules.head.entity.FormTableHead;
import com.teamwings.modules.head.mapper.FormTableHeadMapper;
import com.teamwings.modules.head.service.IFormTableHeadService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author admin
 * @since 2021-05-06
 */
@Service
public class FormTableHeadServiceImpl extends ServiceImpl<FormTableHeadMapper, FormTableHead> implements IFormTableHeadService {

    @Autowired
    private FormTableHeadMapper formTableHeadMapper;
    @Autowired
    private IDesignService designService;
    @Autowired
    private FormTableCodeMapper formTableCodeMapper;
    @Autowired
    private DesignMapper designMapper;
    // 无数据源的表名
    private final String noSourceType = "/";

    @Override
    @Cacheable(value = FormConstant.FORM_HEAD_HEAD, key = "#id")
    public FormTableHead getById(String id) {
        FormTableHead formTableHead = baseMapper.selectById(id);
        return formTableHead;
    }

    @Override
    @Cacheable(value = FormConstant.FORM_HEAD_NAME, key = "#id")
    public String getTableNameById(String id) {
        FormTableHead formTableHead = baseMapper.selectById(id);
        if (formTableHead == null) {
            return null;
        }
        return formTableHead.getTableName();
    }

    @Override
    @Transactional
    @Caching(evict = {
        @CacheEvict(value = FormConstant.FORM_HEAD_COLUMN, key = "#head.id"),
        @CacheEvict(value = FormConstant.FORM_HEAD_HEAD, key = "#head.id"),
        @CacheEvict(value = FormConstant.FORM_HEAD_NAME, key = "#head.id")
    })
    //所有调用保存head方法都应该清除对应缓存，所以将@CacheEvict，从controller移到service
    public Boolean saveMain(FormTableHead head,Boolean isGenerateCode,Boolean isOriginalName) {
        if (head.getDeleted() == null) {
            head.setDeleted(0);
        }

        if (!noSourceType.equals(head.getTableName()) && !isOriginalName) {
            String tableName = generateTableName(head);
            head.setTableName(tableName);
        }

        // 设置版本号
        head.setTableVersion(1);

        Boolean result = save(head);
        //保存tableCode
        if (result && isGenerateCode) {
            saveCode(head);
        }
        return result;
    }

    @Override
    @Caching(evict = {
        @CacheEvict(value = {
            FormConstant.FORM_HEAD_HEAD,
            // FormConstant.FORM_HEAD_COLUMN,
            // FormConstant.FORM_HEAD_CODE
        }, key="#head.id"),
    })
    //所有调用修改head方法都应该清除对应缓存，所以将@CacheEvict，从controller移到service
    public void editMain(FormTableHead head) {
        FormTableHead origin = getById(head.getId());
        // 判断表名是否一致
        if (!origin.getTableName().equals(head.getTableName())) {
            throw new ResultException("数据库表名不能被修改");
        }
        head.setUpdateTime(new Date());
        updateById(head);
    }

    @Override
    public void copyMain(FormTableHead head) {
        FormTableHead f = new FormTableHead();
        f.setId(IdWorker.getIdStr());
        f.setTableCateId(head.getTableCateId());
        f.setTableVersion(head.getTableVersion());
        f.setTableTxt(head.getTableTxt());
        f.setTableCname(head.getTableCname() + "_COPY");
        f.setDeleted(0);
        f.setSourceType(head.getSourceType());
        // 无数据库
        if (noSourceType.equals(head.getTableName())) {
            f.setTableName(head.getTableName());
        } else {
            f.setTableName(head.getTableName() + "_COPY");
        }
        boolean result = save(f);
        // 获取所复制表单的code
        if (result) {
            this.saveCode(f);
            LambdaQueryWrapper<FormTableCode> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(FormTableCode::getTableHeadId, head.getId());
            queryWrapper.orderByAsc(FormTableCode::getTableVersion);
            List<FormTableCode> list = formTableCodeMapper.selectList(queryWrapper);
            list.forEach(k -> {
                FormTableCode t = new FormTableCode();
                BeanUtils.copyProperties(k, t);
                t.setId(null);
                t.setTableHeadId(f.getId());
                t.setUpdateBy(null);
                t.setUpdateTime(null);
                String code = k.getTableCode();
                code = code.replaceAll(head.getId(), f.getId());
                code = code.replaceAll(head.getTableCname(), f.getTableCname());
                code = code.replaceAll(head.getTableName(), f.getTableName());
                t.setTableCode(code);
                LambdaQueryWrapper<FormTableCode> wrapper = Wrappers.lambdaQuery();
                wrapper.eq(FormTableCode::getTableHeadId, f.getId()).eq(FormTableCode::getTableVersion, t.getTableVersion());
                FormTableCode one = formTableCodeMapper.selectOne(wrapper);
                if (one != null) {
                    one.setTableCode(code);
                    formTableCodeMapper.updateById(one);
                }
                designService.edit(code, t.getRemarks());
            });
        }
    }

    @Override
    public Boolean hasTable(String tableName) {
        return baseMapper.hasTable(tableName);
    }

    @Override
    public List<FormTableHead> getLatestList() {
        return baseMapper.getLatestList();
    }

    @Override
    public IPage<FormTableHead> getListWhitCode(IPage<FormTableHead> page, Wrapper<FormTableHead> queryWrapper) {
        return formTableHeadMapper.getListWhitCode(page, queryWrapper);
    }

    /**
     * 生成表名
     * 如果用户设置了，按照用户的表名建表。否则系统自动生成
     */
    private String generateTableName(FormTableHead head) {
        String tableName = "";

        if (StringUtils.isEmpty(head.getTableName())) {
            // 系统自动生成表名
            tableName = "form_user_" + System.currentTimeMillis();
            tableName = tableName.toUpperCase();
        } else {
            // 用户自定义表名
            tableName = ("form_user_" + head.getTableName()).toUpperCase();
        }

        // 判断数据库是否存在该表
        Boolean hasTable = formTableHeadMapper.hasTable(tableName);
        if (hasTable) {
            throw new ResultException("表名已存在");
        }

        return tableName;
    }

    private void saveCode(FormTableHead head) {
        String defaultCode = "{\"config\": {\"datasourceType\": %d, " +
            "\"layout\": \"horizontal\", \"customStyle\": \"\", " +
            "\"wrapperCol\": {\"xl\": 18, \"md\": 18, \"sm\": 18, \"xs\": 18, \"lg\": 18, " +
            "\"xxl\": 18 }, \"hideRequiredMark\": false, \"labelCol\": {\"xl\": 4, \"md\": 4, " +
            "\"sm\": 4, \"xs\": 4, \"lg\": 4, \"xxl\": 4 }, \"formTag\": \"\", \"title\": " +
            "\"%s\", \"tableName\": \"%s\"}, \"list\": [], \"tableHeadId\": " +
            "\"%s\"}";
        defaultCode = String.format(defaultCode, head.getSourceType(),
            head.getTableCname(), head.getTableName(), head.getId());
        //创建head的同时，创建code
        designService.save(defaultCode, head, null);
    }


}
